#include "createcachetaskdialog.h"
#include "ui_createcachetaskdialog.h"
#include "systemparams.h"

#include <QCoreApplication>
#include <QStorageInfo>
#include <QDebug>


CreateCacheTaskDialog::CreateCacheTaskDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::CreateCacheTaskDialog)
{
    ui->setupUi(this);
    this->setWindowTitle("新建缓存任务");
    treeViewCacheTask_init();

    ui->pushButton_next->setEnabled(false);

    connect(m_pModel, SIGNAL(itemChanged(QStandardItem *)), this, SLOT(treeItemChanged(QStandardItem*)));
}

CreateCacheTaskDialog::~CreateCacheTaskDialog()
{
    delete ui;
}

void CreateCacheTaskDialog::createCacheTaskDigShow_slot()
{
    qDebug("%s enter", __func__);

    QString cmd_str = QString("echo \"%1\"|sudo -S %2").arg(SystemParams::instance_get()->m_userPasswd)
                                              .arg(QString(CMD_LSBLK));
    emit shellProcessCmdWrite_signal(cmd_str, this);

    m_blockSelected.clear();
    ui->pushButton_next->setEnabled(false);

    setModal(true);
    show();
}

void CreateCacheTaskDialog::shellProcessCmdReadOutput_slot(QString &content, QObject* from)
{
    if (from != this)
    {
        return;
    }

    qDebug("%s content:%s", __func__, content.toLatin1().data());

    m_pModel->clear();
    m_disksList.clear();

    blockdevicesJson_parse(content);
    treeViewCacheTask_update();
}

void CreateCacheTaskDialog::treeItemChanged(QStandardItem *item)
{
    qDebug("%s enter!", __func__);

    if ( item == NULL)
        return ;

    if ( item->isCheckable ())
    {
        //如果条目是存在复选框的，那么就进行下面的操作
        Qt::CheckState state = item->checkState (); //获取当前的选择状态
        if (item->isTristate())
        {
            //如果条目是三态的，说明可以对子目录进行全选和全不选的设置
            if ( state != Qt::PartiallyChecked )
            {
                //当前是选中状态，需要对其子项目进行全选
                treeItem_checkAllChild (item , state == Qt::Checked ? true : false );
            }
        }
        else
        {
            //说明是两态的，两态会对父级的三态有影响
            //判断兄弟节点的情况
            treeItem_CheckChildChanged(item);
        }
    }

    blockCheckedList_get();

    if (blockSelectedNoEmpty_check())
    {
        ui->pushButton_next->setEnabled(true);
    }
    else
    {
        ui->pushButton_next->setEnabled(false);
    }
}

void CreateCacheTaskDialog::treeItem_checkAllChild(QStandardItem * item, bool check)
{
    if(item == NULL)
        return;
    int rowCount = item->rowCount();
    for(int i=0;i<rowCount;++i)
    {
        QStandardItem* childItems = item->child(i);
        treeItem_checkAllChild_recursion(childItems,check);
    }

    if(item->isCheckable())
           item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}

void CreateCacheTaskDialog::treeItem_checkAllChild_recursion(QStandardItem * item,bool check)
{
    if(item == NULL)
        return;
    int rowCount = item->rowCount();
    for(int i=0;i<rowCount;++i)
    {
        QStandardItem* childItems = item->child(i);
        treeItem_checkAllChild_recursion(childItems,check);
    }
    if(item->isCheckable())
        item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}

void CreateCacheTaskDialog::treeItem_CheckChildChanged(QStandardItem * item)
{
    if (item==NULL)
        return;
    Qt::CheckState siblingState = checkSibling(item);
    QStandardItem * parentItem = item->parent();
    if(NULL == parentItem)
        return;
    if(Qt::PartiallyChecked == siblingState)
    {
        if(parentItem->isCheckable() && parentItem->isTristate())
            parentItem->setCheckState(Qt::PartiallyChecked);
    }
    else if(Qt::Checked == siblingState)
    {
        if(parentItem->isCheckable())
            parentItem->setCheckState(Qt::Checked);
    }
    else
    {
        if(parentItem->isCheckable())
            parentItem->setCheckState(Qt::Unchecked);
    }
    treeItem_CheckChildChanged(parentItem);
}

//
// \brief 测量兄弟节点的情况，如果都选中返回Qt::Checked，都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
// \param item
// \return 如果都选中返回Qt::Checked，都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
//

Qt::CheckState CreateCacheTaskDialog::checkSibling(QStandardItem * item)
{
    //先通过父节点获取兄弟节点
    QStandardItem * parent = item->parent();
    if(NULL == parent)
        return item->checkState();
    int brotherCount = parent->rowCount();
    int checkedCount(0),unCheckedCount(0);
    Qt::CheckState state;
    for(int i=0;i<brotherCount;++i)
    {
        QStandardItem* siblingItem = parent->child(i);
        state = siblingItem->checkState();
        if(Qt::PartiallyChecked == state)
            return Qt::PartiallyChecked;
        else if(Qt::Unchecked == state)
            ++unCheckedCount;
        else
            ++checkedCount;
        if(checkedCount>0 && unCheckedCount>0)
            return Qt::PartiallyChecked;
    }
    if(unCheckedCount>0)
        return Qt::Unchecked;
    return Qt::Checked;
}


void CreateCacheTaskDialog::blockdevicesJson_parse(QString &content)
{
    QJsonParseError json_error;
    QJsonDocument jsonDoc=QJsonDocument::fromJson(content.toLocal8Bit(), &json_error);
    if(json_error.error != QJsonParseError::NoError)
    {
         qWarning("%s parse json error!", __func__);
         return;
    }

    if (!jsonDoc.isObject())
    {
        qWarning("%s json is not object", __func__);
        return;
    }

    QJsonObject obj_root = jsonDoc.object();
    QJsonArray array_blockdevices = obj_root["blockdevices"].toArray();
    for (uint16 i=0; i<array_blockdevices.size(); i++)
    {
        QJsonObject object_device = array_blockdevices[i].toObject();
        if (!object_device.isEmpty())
        {
            qDebug("name=%s", object_device["name"].toString().toLocal8Bit().data());
        }

        QList<QStandardItem*> items_device;
        QStandardItem* item_name = new QStandardItem(object_device["name"].toString());
        item_name->setCheckable(true);
        item_name->setTristate(true);
        QStandardItem* item_type = new QStandardItem(object_device["type"].toString());
        QStandardItem* item_size = new QStandardItem(object_device["size"].toString());
        QStandardItem* item_mountpoint = new QStandardItem(object_device["mountpoint"].toString());

        items_device.append(item_name);
        items_device.append(item_type);
        items_device.append(item_size);
        items_device.append(item_mountpoint);
        m_pModel->appendRow(items_device);

        if (object_device["type"].toString()==BLOCK_TYPE_DISK)
        {
            Block_Info info;
            info.m_name = object_device["name"].toString();
            info.m_type = Block_Info::IS_DISK;
            info.m_size = object_device["size"].toString();

            m_disksList << info;
        }

        QJsonArray array_child=object_device["children"].toArray();
        for (uint16 j=0; j<array_child.size(); j++)
        {
            QJsonObject object_partition = array_child[j].toObject();
            qDebug("partition=%s", object_partition["name"].toString().toLocal8Bit().data());

            QList<QStandardItem*> items_partition;
            QStandardItem* item_name_p = new QStandardItem(object_partition["name"].toString());
            item_name_p->setCheckable(true);
            QStandardItem* item_type_p = new QStandardItem(object_partition["type"].toString());
            QStandardItem* item_size_p = new QStandardItem(object_partition["size"].toString());
            QStandardItem* item_mountpoint_p = new QStandardItem(object_partition["mountpoint"].toString());

            items_partition.append(item_name_p);
            items_partition.append(item_type_p);
            items_partition.append(item_size_p);
            items_partition.append(item_mountpoint_p);

            item_name->appendRow(items_partition);
        }
    }
}

void CreateCacheTaskDialog::treeViewCacheTask_init()
{
    m_pModel = new QStandardItemModel(ui->treeView_diskInfo);
    ui->treeView_diskInfo->setModel(m_pModel);
}

void CreateCacheTaskDialog::treeViewCacheTask_update()
{
    m_pModel->setHorizontalHeaderLabels(QStringList()<<QString::fromUtf8("名称")
                                     <<QString::fromUtf8("类型") <<QString::fromUtf8("容量")
                                     <<QString::fromUtf8("挂载点"));

    ui->treeView_diskInfo->setColumnWidth(0, 150);
    ui->treeView_diskInfo->setColumnWidth(1, 100);
    ui->treeView_diskInfo->setColumnWidth(2, 100);
    ui->treeView_diskInfo->setColumnWidth(3, 100);
    ui->treeView_diskInfo->expandAll();
}

void CreateCacheTaskDialog::blockCheckedList_get()
{
    m_blockSelected.clear();

    int32 row_num = m_pModel->rowCount();
    qDebug("%s row_num=%d", __func__, row_num);
    for (int32 i=0; i<row_num; i++)
    {
        QStandardItem* item = m_pModel->item(i, 0);
        if (item->checkState()==Qt::Checked)
        {
            QStandardItem* item_type = m_pModel->item(i, 1);
            QStandardItem* item_size = m_pModel->item(i, 2);
            QStandardItem* item_mounted = m_pModel->item(i, 3);

            Block_Info info;
            info.m_name = item->text();

            info.m_type = Block_Info::IS_DISK;
            if (item_type->text()==QString(BLOCK_TYPE_ROM))
            {
                info.m_type = Block_Info::IS_ROM;
            }
            else if (item_type->text()==QString(BLOCK_TYPE_PART))
            {
                info.m_type = Block_Info::IS_PARTITION;
            }

            info.m_size = item_size->text();
            info.m_mountedPoint = item_mounted->text();

            m_blockSelected <<info;
        }
        else if (item->checkState()==Qt::PartiallyChecked)
        {
            int32 child_row_num = item->rowCount();
            qDebug("%s child_row_num=%d", __func__, child_row_num);
            for (int32 j=0; j<child_row_num; j++)
            {
                 QStandardItem* item_child = item->child(j,0);
                 if (item_child->checkState()==Qt::Checked)
                 {
                     QStandardItem* item_child_size = item->child(j, 2);
                     QStandardItem* item_child_mounted = item->child(j, 3);

                     Block_Info info;
                     info.m_name = item_child->text();
                     info.m_type = Block_Info::IS_PARTITION;
                     info.m_size = item_child_size->text();
                     info.m_mountedPoint = item_child_mounted->text();

                     m_blockSelected <<info;
                 }
            }
        }
    }
}

bool CreateCacheTaskDialog::blockSelectedNoEmpty_check()
{
    if (m_blockSelected.isEmpty())
    {
        return false;
    }

   return true;
}

void CreateCacheTaskDialog::on_pushButton_next_clicked()
{
    hide();
    emit cacheTaskParamsSetDigShow_signal(&m_blockSelected, &m_disksList);
}

void CreateCacheTaskDialog::on_pushButton_cancel_clicked()
{
    hide();
}
